home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / Perl / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-01  |  31.1 KB  |  1,339 lines

  1. /* $RCSfile: cmd.c,v $$Revision: 1.2 $$Date: 1994/05/04 02:08:55 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log: cmd.c,v $
  9.  * Revision 1.2  1994/05/04  02:08:55  neeri
  10.  * Avoid desaster on chop of undefined strings.
  11.  *
  12.  * Revision 4.0.1.5  92/06/08  12:00:39  lwall
  13.  * patch20: the switch optimizer didn't do anything in subroutines
  14.  * patch20: removed implicit int declarations on funcions
  15.  * 
  16.  * Revision 4.0.1.4  91/11/11  16:29:33  lwall
  17.  * patch19: do {$foo ne "bar";} returned wrong value
  18.  * patch19: some earlier patches weren't propagated to alternate 286 code
  19.  * 
  20.  * Revision 4.0.1.3  91/11/05  16:07:43  lwall
  21.  * patch11: random cleanup
  22.  * patch11: "foo\0" eq "foo" was sometimes optimized to true
  23.  * patch11: foreach on null list could spring memory leak
  24.  * 
  25.  * Revision 4.0.1.2  91/06/07  10:26:45  lwall
  26.  * patch4: new copyright notice
  27.  * patch4: made some allowances for "semi-standard" C
  28.  * 
  29.  * Revision 4.0.1.1  91/04/11  17:36:16  lwall
  30.  * patch1: you may now use "die" and "caller" in a signal handler
  31.  * 
  32.  * Revision 4.0  91/03/20  01:04:18  lwall
  33.  * 4.0 baseline.
  34.  * 
  35.  */
  36.  
  37. #include "EXTERN.h"
  38. #include "perl.h"
  39.  
  40. #ifdef I_VARARGS
  41. #  include <varargs.h>
  42. #endif
  43.  
  44. static STR strchop;
  45.  
  46. void grow_dlevel();
  47.  
  48. /* do longjmps() clobber register variables? */
  49.  
  50. #if defined(cray) || defined(STDMAC)
  51. #define JMPCLOBBER
  52. #endif
  53.  
  54. /* This is the main command loop.  We try to spend as much time in this loop
  55.  * as possible, so lots of optimizations do their activities in here.  This
  56.  * means things get a little sloppy.
  57.  */
  58.  
  59. int
  60. cmd_exec(cmdparm,gimme,sp)
  61. CMD *VOLATILE cmdparm;
  62. VOLATILE int gimme;
  63. VOLATILE int sp;
  64. {
  65.     register CMD *cmd = cmdparm;
  66.     SPAT *VOLATILE oldspat;
  67.     VOLATILE int firstsave = savestack->ary_fill;
  68.     VOLATILE int oldsave;
  69.     VOLATILE int aryoptsave;
  70. #ifdef DEBUGGING
  71.     VOLATILE int olddlevel;
  72.     VOLATILE int entdlevel;
  73. #endif
  74.     register STR *retstr = &str_undef;
  75.     register char *tmps;
  76.     register int cmdflags;
  77.     register int match;
  78.     register char *go_to = goto_targ;
  79.     register int newsp = -2;
  80.     register STR **st = stack->ary_array;
  81.     FILE *VOLATILE fp;
  82.     ARRAY *VOLATILE ar;
  83.  
  84.     lastsize = 0;
  85. #ifdef DEBUGGING
  86.     entdlevel = dlevel;
  87. #endif
  88. tail_recursion_entry:
  89.  
  90. #ifdef macintosh
  91.     SpinMacCursor();
  92. #endif
  93.  
  94. #ifdef DEBUGGING
  95.     dlevel = entdlevel;
  96.     if (debug & 4)
  97.     deb("mortals = (%d/%d) stack, = (%d/%d)\n",
  98.         tmps_max, tmps_base,
  99.         savestack->ary_fill, firstsave);
  100. #endif
  101. #ifdef TAINT
  102.     tainted = 0;    /* Each statement is presumed innocent */
  103. #endif
  104.     if (cmd == Nullcmd) {
  105.     if (gimme == G_ARRAY && newsp > -2)
  106.         return newsp;
  107.     else {
  108.         st[++sp] = retstr;
  109.         return sp;
  110.     }
  111.     }
  112.     cmdflags = cmd->c_flags;    /* hopefully load register */
  113.     if (go_to) {
  114.     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  115.         goto_targ = go_to = Nullch;        /* here at last */
  116.     else {
  117.  
  118. #ifdef macintosh
  119.    SpinMacCursor();
  120. #endif
  121.  
  122.         switch (cmd->c_type) {
  123.         case C_IF:
  124.         oldspat = curspat;
  125.         oldsave = savestack->ary_fill;
  126. #ifdef DEBUGGING
  127.         olddlevel = dlevel;
  128. #endif
  129.         retstr = &str_yes;
  130.         newsp = -2;
  131.         if (cmd->ucmd.ccmd.cc_true) {
  132. #ifdef DEBUGGING
  133.             if (debug) {
  134.             debname[dlevel] = 't';
  135.             debdelim[dlevel] = '_';
  136.             if (++dlevel >= dlmax)
  137.                 grow_dlevel();
  138.             }
  139. #endif
  140.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  141.             st = stack->ary_array;    /* possibly reallocated */
  142.             retstr = st[newsp];
  143.         }
  144.         if (!goto_targ)
  145.             go_to = Nullch;
  146.         curspat = oldspat;
  147.         if (savestack->ary_fill > oldsave)
  148.             restorelist(oldsave);
  149. #ifdef DEBUGGING
  150.         dlevel = olddlevel;
  151. #endif
  152.         cmd = cmd->ucmd.ccmd.cc_alt;
  153.         goto tail_recursion_entry;
  154.         case C_ELSE:
  155.         oldspat = curspat;
  156.         oldsave = savestack->ary_fill;
  157. #ifdef DEBUGGING
  158.         olddlevel = dlevel;
  159. #endif
  160.         retstr = &str_undef;
  161.         newsp = -2;
  162.         if (cmd->ucmd.ccmd.cc_true) {
  163. #ifdef DEBUGGING
  164.             if (debug) {
  165.             debname[dlevel] = 'e';
  166.             debdelim[dlevel] = '_';
  167.             if (++dlevel >= dlmax)
  168.                 grow_dlevel();
  169.             }
  170. #endif
  171.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  172.             st = stack->ary_array;    /* possibly reallocated */
  173.             retstr = st[newsp];
  174.         }
  175.         if (!goto_targ)
  176.             go_to = Nullch;
  177.         curspat = oldspat;
  178.         if (savestack->ary_fill > oldsave)
  179.             restorelist(oldsave);
  180. #ifdef DEBUGGING
  181.         dlevel = olddlevel;
  182. #endif
  183.         break;
  184.         case C_BLOCK:
  185.         case C_WHILE:
  186.         if (!(cmdflags & CF_ONCE)) {
  187.             cmdflags |= CF_ONCE;
  188.             if (++loop_ptr >= loop_max) {
  189.             loop_max += 128;
  190.             Renew(loop_stack, loop_max, struct loop);
  191.             }
  192.             loop_stack[loop_ptr].loop_label = cmd->c_label;
  193.             loop_stack[loop_ptr].loop_sp = sp;
  194. #ifdef DEBUGGING
  195.             if (debug & 4) {
  196.             deb("(Pushing label #%d %s)\n",
  197.               loop_ptr, cmd->c_label ? cmd->c_label : "");
  198.             }
  199. #endif
  200.         }
  201. #ifdef JMPCLOBBER
  202.         cmdparm = cmd;
  203. #endif
  204.         match = setjmp(loop_stack[loop_ptr].loop_env);
  205.         if (match) {
  206.             st = stack->ary_array;    /* possibly reallocated */
  207. #ifdef JMPCLOBBER
  208.             cmd = cmdparm;
  209.             cmdflags = cmd->c_flags|CF_ONCE;
  210. #endif
  211.             if (savestack->ary_fill > oldsave)
  212.             restorelist(oldsave);
  213.             switch (match) {
  214.             default:
  215.             fatal("longjmp returned bad value (%d)",match);
  216.             case O_LAST:    /* not done unless go_to found */
  217.             go_to = Nullch;
  218.             if (lastretstr) {
  219.                 retstr = lastretstr;
  220.                 newsp = -2;
  221.             }
  222.             else {
  223.                 newsp = sp + lastsize;
  224.                 retstr = st[newsp];
  225.             }
  226. #ifdef DEBUGGING
  227.             olddlevel = dlevel;
  228. #endif
  229.             curspat = oldspat;
  230.             goto next_cmd;
  231.             case O_NEXT:    /* not done unless go_to found */
  232.             go_to = Nullch;
  233. #ifdef JMPCLOBBER
  234.             newsp = -2;
  235.             retstr = &str_undef;
  236. #endif
  237.             goto next_iter;
  238.             case O_REDO:    /* not done unless go_to found */
  239.             go_to = Nullch;
  240. #ifdef JMPCLOBBER
  241.             newsp = -2;
  242.             retstr = &str_undef;
  243. #endif
  244.             goto doit;
  245.             }
  246.         }
  247.         oldspat = curspat;
  248.         oldsave = savestack->ary_fill;
  249. #ifdef DEBUGGING
  250.         olddlevel = dlevel;
  251. #endif
  252.         if (cmd->ucmd.ccmd.cc_true) {
  253. #ifdef DEBUGGING
  254.             if (debug) {
  255.             debname[dlevel] = 't';
  256.             debdelim[dlevel] = '_';
  257.             if (++dlevel >= dlmax)
  258.                 grow_dlevel();
  259.             }
  260. #endif
  261.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  262.             st = stack->ary_array;    /* possibly reallocated */
  263.             if (newsp >= 0)
  264.             retstr = st[newsp];
  265.         }
  266.         if (!goto_targ) {
  267.             go_to = Nullch;
  268.             goto next_iter;
  269.         }
  270. #ifdef DEBUGGING
  271.         dlevel = olddlevel;
  272. #endif
  273.         if (cmd->ucmd.ccmd.cc_alt) {
  274. #ifdef DEBUGGING
  275.             if (debug) {
  276.             debname[dlevel] = 'a';
  277.             debdelim[dlevel] = '_';
  278.             if (++dlevel >= dlmax)
  279.                 grow_dlevel();
  280.             }
  281. #endif
  282.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  283.             st = stack->ary_array;    /* possibly reallocated */
  284.             if (newsp >= 0)
  285.             retstr = st[newsp];
  286.         }
  287.         if (goto_targ)
  288.             break;
  289.         go_to = Nullch;
  290.         goto finish_while;
  291.         }
  292.         cmd = cmd->c_next;
  293.         if (cmd && cmd->c_head == cmd)
  294.                     /* reached end of while loop */
  295.         return sp;        /* targ isn't in this block */
  296.         if (cmdflags & CF_ONCE) {
  297. #ifdef DEBUGGING
  298.         if (debug & 4) {
  299.             tmps = loop_stack[loop_ptr].loop_label;
  300.             deb("(Popping label #%d %s)\n",loop_ptr,
  301.             tmps ? tmps : "" );
  302.         }
  303. #endif
  304.         loop_ptr--;
  305.         }
  306.         goto tail_recursion_entry;
  307.     }
  308.     }
  309.  
  310. until_loop:
  311.  
  312. #ifdef macintosh
  313.     SpinMacCursor();
  314. #endif
  315.  
  316.     /* Set line number so run-time errors can be located */
  317.  
  318.     curcmd = cmd;
  319.  
  320. #ifdef DEBUGGING
  321.     if (debug) {
  322.     if (debug & 2) {
  323.         deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  324.         cmdname[cmd->c_type],cmd,cmd->c_expr,
  325.         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  326.         curspat);
  327.     }
  328.     debname[dlevel] = cmdname[cmd->c_type][0];
  329.     debdelim[dlevel] = '!';
  330.     if (++dlevel >= dlmax)
  331.         grow_dlevel();
  332.     }
  333. #endif
  334.  
  335. #ifdef macintosh
  336.     SpinMacCursor();
  337. #endif
  338.  
  339.     /* Here is some common optimization */
  340.  
  341.     if (cmdflags & CF_COND) {
  342.     switch (cmdflags & CF_OPTIMIZE) {
  343.  
  344.     case CFT_FALSE:
  345.         retstr = cmd->c_short;
  346.         newsp = -2;
  347.         match = FALSE;
  348.         if (cmdflags & CF_NESURE)
  349.         goto maybe;
  350.         break;
  351.     case CFT_TRUE:
  352.         retstr = cmd->c_short;
  353.         newsp = -2;
  354.         match = TRUE;
  355.         if (cmdflags & CF_EQSURE)
  356.         goto flipmaybe;
  357.         break;
  358.  
  359.     case CFT_REG:
  360.         retstr = STAB_STR(cmd->c_stab);
  361.         newsp = -2;
  362.         match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  363.         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  364.         goto flipmaybe;
  365.         break;
  366.  
  367.     case CFT_ANCHOR:    /* /^pat/ optimization */
  368.         if (multiline) {
  369.         if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  370.             goto scanner;    /* just unanchor it */
  371.         else
  372.             break;        /* must evaluate */
  373.         }
  374.         match = 0;
  375.         goto strop;
  376.  
  377.     case CFT_STROP:        /* string op optimization */
  378.         match = 1;
  379.       strop:
  380.         retstr = STAB_STR(cmd->c_stab);
  381.         newsp = -2;
  382. #ifndef I286
  383.         if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  384.             (match ? retstr->str_cur == cmd->c_slen - 1 :
  385.                      retstr->str_cur >= cmd->c_slen) &&
  386.             bcmp(cmd->c_short->str_ptr, str_get(retstr),
  387.               cmd->c_slen) == 0 ) {
  388.         if (cmdflags & CF_EQSURE) {
  389.             if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  390.             curspat = Nullspat;
  391.             if (leftstab)
  392.                 str_nset(stab_val(leftstab),"",0);
  393.             if (amperstab)
  394.                 str_sset(stab_val(amperstab),cmd->c_short);
  395.             if (rightstab)
  396.                 str_nset(stab_val(rightstab),
  397.                   retstr->str_ptr + cmd->c_slen,
  398.                   retstr->str_cur - cmd->c_slen);
  399.             }
  400.             if (cmd->c_spat)
  401.             lastspat = cmd->c_spat;
  402.             match = !(cmdflags & CF_FIRSTNEG);
  403.             retstr = match ? &str_yes : &str_no;
  404.             goto flipmaybe;
  405.         }
  406.         }
  407.         else if (cmdflags & CF_NESURE) {
  408.         match = cmdflags & CF_FIRSTNEG;
  409.         retstr = match ? &str_yes : &str_no;
  410.         goto flipmaybe;
  411.         }
  412. #else
  413.         {
  414.         char *zap1, *zap2, zap1c, zap2c;
  415.         int  zaplen;
  416.         int lenok;
  417.  
  418.         zap1 = cmd->c_short->str_ptr;
  419.         zap2 = str_get(retstr);
  420.         zap1c = *zap1;
  421.         zap2c = *zap2;
  422.         zaplen = cmd->c_slen;
  423.         if (match)
  424.             lenok = (retstr->str_cur == cmd->c_slen - 1);
  425.         else
  426.             lenok = (retstr->str_cur >= cmd->c_slen);
  427.         if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
  428.             if (cmdflags & CF_EQSURE) {
  429.             if (sawampersand &&
  430.               (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  431.                 curspat = Nullspat;
  432.                 if (leftstab)
  433.                 str_nset(stab_val(leftstab),"",0);
  434.                 if (amperstab)
  435.                 str_sset(stab_val(amperstab),cmd->c_short);
  436.                 if (rightstab)
  437.                 str_nset(stab_val(rightstab),
  438.                      retstr->str_ptr + cmd->c_slen,
  439.                      retstr->str_cur - cmd->c_slen);
  440.             }
  441.             if (cmd->c_spat)
  442.                 lastspat = cmd->c_spat;
  443.              match = !(cmdflags & CF_FIRSTNEG);
  444.             retstr = match ? &str_yes : &str_no;
  445.              goto flipmaybe;
  446.             }
  447.         }
  448.         else if (cmdflags & CF_NESURE) {
  449.             match = cmdflags & CF_FIRSTNEG;
  450.             retstr = match ? &str_yes : &str_no;
  451.             goto flipmaybe;
  452.         }
  453.         }
  454. #endif
  455.         break;            /* must evaluate */
  456.  
  457.     case CFT_SCAN:            /* non-anchored search */
  458.       scanner:
  459.         retstr = STAB_STR(cmd->c_stab);
  460.         newsp = -2;
  461.         if (retstr->str_pok & SP_STUDIED)
  462.         if (screamfirst[cmd->c_short->str_rare] >= 0)
  463.             tmps = screaminstr(retstr, cmd->c_short);
  464.         else
  465.             tmps = Nullch;
  466.         else {
  467.         tmps = str_get(retstr);        /* make sure it's pok */
  468. #ifndef lint
  469.         tmps = fbminstr((unsigned char*)tmps,
  470.             (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  471. #endif
  472.         }
  473.         if (tmps) {
  474.         if (cmdflags & CF_EQSURE) {
  475.             ++cmd->c_short->str_u.str_useful;
  476.             if (sawampersand) {
  477.             curspat = Nullspat;
  478.             if (leftstab)
  479.                 str_nset(stab_val(leftstab),retstr->str_ptr,
  480.                   tmps - retstr->str_ptr);
  481.             if (amperstab)
  482.                 str_nset(stab_val(amperstab),
  483.                   tmps, cmd->c_short->str_cur);
  484.             if (rightstab)
  485.                 str_nset(stab_val(rightstab),
  486.                   tmps + cmd->c_short->str_cur,
  487.                   retstr->str_cur - (tmps - retstr->str_ptr) -
  488.                 cmd->c_short->str_cur);
  489.             }
  490.             lastspat = cmd->c_spat;
  491.             match = !(cmdflags & CF_FIRSTNEG);
  492.             retstr = match ? &str_yes : &str_no;
  493.             goto flipmaybe;
  494.         }
  495.         else
  496.             hint = tmps;
  497.         }
  498.         else {
  499.         if (cmdflags & CF_NESURE) {
  500.             ++cmd->c_short->str_u.str_useful;
  501.             match = cmdflags & CF_FIRSTNEG;
  502.             retstr = match ? &str_yes : &str_no;
  503.             goto flipmaybe;
  504.         }
  505.         }
  506.         if (--cmd->c_short->str_u.str_useful < 0) {
  507.         cmdflags &= ~CF_OPTIMIZE;
  508.         cmdflags |= CFT_EVAL;    /* never try this optimization again */
  509.         cmd->c_flags = (cmdflags & ~CF_ONCE);
  510.         }
  511.         break;            /* must evaluate */
  512.  
  513.     case CFT_NUMOP:        /* numeric op optimization */
  514.         retstr = STAB_STR(cmd->c_stab);
  515.         newsp = -2;
  516.         switch (cmd->c_slen) {
  517.         case O_EQ:
  518.         if (dowarn) {
  519.             if ((!retstr->str_nok && !looks_like_number(retstr)))
  520.             warn("Possible use of == on string value");
  521.         }
  522.         match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  523.         break;
  524.         case O_NE:
  525.         match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  526.         break;
  527.         case O_LT:
  528.         match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  529.         break;
  530.         case O_LE:
  531.         match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  532.         break;
  533.         case O_GT:
  534.         match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  535.         break;
  536.         case O_GE:
  537.         match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  538.         break;
  539.         }
  540.         if (match) {
  541.         if (cmdflags & CF_EQSURE) {
  542.             retstr = &str_yes;
  543.             goto flipmaybe;
  544.         }
  545.         }
  546.         else if (cmdflags & CF_NESURE) {
  547.         retstr = &str_no;
  548.         goto flipmaybe;
  549.         }
  550.         break;            /* must evaluate */
  551.  
  552.     case CFT_INDGETS:        /* while (<$foo>) */
  553.         last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  554.         if (!stab_io(last_in_stab))
  555.         stab_io(last_in_stab) = stio_new();
  556.         goto dogets;
  557.     case CFT_GETS:            /* really a while (<file>) */
  558.         last_in_stab = cmd->c_stab;
  559.       dogets:
  560.         fp = stab_io(last_in_stab)->ifp;
  561.         retstr = stab_val(defstab);
  562.         newsp = -2;
  563.       keepgoing:
  564.         if (fp && str_gets(retstr, fp, 0)) {
  565.         if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  566.             match = FALSE;
  567.         else
  568.             match = TRUE;
  569.         stab_io(last_in_stab)->lines++;
  570.         }
  571.         else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  572.         if (!fp)
  573.             goto doeval;    /* first time through */
  574.         fp = nextargv(last_in_stab);
  575.         if (fp)
  576.             goto keepgoing;
  577.         (void)do_close(last_in_stab,FALSE);
  578.         stab_io(last_in_stab)->flags |= IOF_START;
  579.         retstr = &str_undef;
  580.         match = FALSE;
  581.         }
  582.         else {
  583.         retstr = &str_undef;
  584.         match = FALSE;
  585.         }
  586.         goto flipmaybe;
  587.     case CFT_EVAL:
  588.         break;
  589.     case CFT_UNFLIP:
  590.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  591.         str_free(tmps_list[tmps_max]);
  592.         tmps_list[tmps_max--] = Nullstr;
  593.         }
  594.         newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  595.         st = stack->ary_array;    /* possibly reallocated */
  596.         retstr = st[newsp];
  597.         match = str_true(retstr);
  598.         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  599.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  600.         goto maybe;
  601.     case CFT_CHOP:
  602.         retstr = stab_val(cmd->c_stab);
  603.         newsp = -2;
  604. /* I don't remember why I did this╔ Nuke it MN ifdef macintosh
  605.         tmps = str_get(retstr);
  606.         match = (retstr->str_cur != 0);
  607. else
  608. */
  609.         match = (retstr->str_cur != 0);
  610.         tmps = str_get(retstr);
  611. /* endif */
  612.         tmps += retstr->str_cur - match;
  613.         str_nset(&strchop,tmps,match);
  614.         *tmps = '\0';
  615.         retstr->str_nok = 0;
  616.         retstr->str_cur = tmps - retstr->str_ptr;
  617.         STABSET(retstr);
  618.         retstr = &strchop;
  619.          goto flipmaybe;
  620.     case CFT_ARRAY:
  621.         match = cmd->c_short->str_u.str_useful; /* just to get register */
  622.  
  623.         if (match < 0) {        /* first time through here? */
  624.         ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  625.         aryoptsave = savestack->ary_fill;
  626.         savesptr(&stab_val(cmd->c_stab));
  627.         savelong(&cmd->c_short->str_u.str_useful);
  628.         }
  629.         else {
  630.         ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
  631.         if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
  632.             restorelist(firstsave);
  633.         }
  634.  
  635.         if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  636.         if (match < 0 &&        /* er, probably not... */
  637.           savestack->ary_fill > aryoptsave)
  638.             restorelist(aryoptsave);
  639.         retstr = &str_undef;
  640.         cmd->c_short->str_u.str_useful = -1;    /* actually redundant */
  641.         match = FALSE;
  642.         }
  643.         else {
  644.         match++;
  645.         if (!(retstr = ar->ary_array[match]))
  646.             retstr = afetch(ar,match,TRUE);
  647.         stab_val(cmd->c_stab) = retstr;
  648.         cmd->c_short->str_u.str_useful = match;
  649.         match = TRUE;
  650.         }
  651.         newsp = -2;
  652.         goto maybe;
  653.     case CFT_D1:
  654.         break;
  655.     case CFT_D0:
  656.         if (DBsingle->str_u.str_nval != 0)
  657.         break;
  658.         if (DBsignal->str_u.str_nval != 0)
  659.         break;
  660.         if (DBtrace->str_u.str_nval != 0)
  661.         break;
  662.         goto next_cmd;
  663.     }
  664.  
  665.     /* we have tried to make this normal case as abnormal as possible */
  666.  
  667.     doeval:
  668.  
  669. #ifdef macintosh
  670.     SpinMacCursor();
  671. #endif
  672.  
  673.     if (gimme == G_ARRAY) {
  674.         lastretstr = Nullstr;
  675.         lastspbase = sp;
  676.         lastsize = newsp - sp;
  677.         if (lastsize < 0)
  678.         lastsize = 0;
  679.     }
  680.     else
  681.         lastretstr = retstr;
  682.     while (tmps_max > tmps_base) {    /* clean up after last eval */
  683.         str_free(tmps_list[tmps_max]);
  684.         tmps_list[tmps_max--] = Nullstr;
  685.     }
  686.     newsp = eval(cmd->c_expr,
  687.       gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
  688.         !cmd->ucmd.acmd.ac_expr,
  689.       sp);
  690.     st = stack->ary_array;    /* possibly reallocated */
  691.     retstr = st[newsp];
  692.     if (newsp > sp && retstr)
  693.         match = str_true(retstr);
  694.     else
  695.         match = FALSE;
  696.     goto maybe;
  697.  
  698.     /* if flipflop was true, flop it */
  699.  
  700.     flipmaybe:
  701.  
  702. #ifdef macintosh
  703.     SpinMacCursor();
  704. #endif
  705.  
  706.     if (match && cmdflags & CF_FLIP) {
  707.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  708.         str_free(tmps_list[tmps_max]);
  709.         tmps_list[tmps_max--] = Nullstr;
  710.         }
  711.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  712.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  713.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  714.         }
  715.         else {
  716.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  717.         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  718.             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  719.         }
  720.     }
  721.     else if (cmdflags & CF_FLIP) {
  722.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  723.         match = TRUE;                /* force on */
  724.         }
  725.     }
  726.  
  727.     /* at this point, match says whether our expression was true */
  728.  
  729.     maybe:
  730.  
  731. #ifdef macintosh
  732.    SpinMacCursor();
  733. #endif
  734.  
  735.     if (cmdflags & CF_INVERT)
  736.         match = !match;
  737.     if (!match)
  738.         goto next_cmd;
  739.     }
  740. #ifdef TAINT
  741.     tainted = 0;    /* modifier doesn't affect regular expression */
  742. #endif
  743.  
  744.     /* now to do the actual command, if any */
  745.  
  746. #ifdef macintosh
  747.     SpinMacCursor();
  748. #endif
  749.  
  750.     switch (cmd->c_type) {
  751.     case C_NULL:
  752.     fatal("panic: cmd_exec");
  753.     case C_EXPR:            /* evaluated for side effects */
  754.     if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  755.         if (gimme == G_ARRAY) {
  756.         lastretstr = Nullstr;
  757.         lastspbase = sp;
  758.         lastsize = newsp - sp;
  759.         if (lastsize < 0)
  760.             lastsize = 0;
  761.         }
  762.         else
  763.         lastretstr = retstr;
  764.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  765.         str_free(tmps_list[tmps_max]);
  766.         tmps_list[tmps_max--] = Nullstr;
  767.         }
  768.         newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  769.         st = stack->ary_array;    /* possibly reallocated */
  770.         retstr = st[newsp];
  771.     }
  772.     break;
  773.     case C_NSWITCH:
  774.     {
  775.         double value = str_gnum(STAB_STR(cmd->c_stab));
  776.  
  777.         match = (int)value;
  778.         if (value < 0.0) {
  779.         if (((double)match) > value)
  780.             --match;        /* was fractional--truncate other way */
  781.         }
  782.     }
  783.  
  784. #ifdef macintosh
  785.    SpinMacCursor();
  786. #endif
  787.  
  788.     goto doswitch;
  789.     case C_CSWITCH:
  790.     if (multiline) {
  791.         cmd = cmd->c_next;            /* can't assume anything */
  792.         goto tail_recursion_entry;
  793.     }
  794.     match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  795.       doswitch:
  796.     match -= cmd->ucmd.scmd.sc_offset;
  797.     if (match < 0)
  798.         match = 0;
  799.     else if (match > cmd->ucmd.scmd.sc_max)
  800.         match = cmd->ucmd.scmd.sc_max;
  801.     cmd = cmd->ucmd.scmd.sc_next[match];
  802.     goto tail_recursion_entry;
  803.     case C_NEXT:
  804.     cmd = cmd->ucmd.ccmd.cc_alt;
  805.     goto tail_recursion_entry;
  806.     case C_ELSIF:
  807.     fatal("panic: ELSIF");
  808.     case C_IF:
  809.     oldspat = curspat;
  810.     oldsave = savestack->ary_fill;
  811. #ifdef DEBUGGING
  812.     olddlevel = dlevel;
  813. #endif
  814.     retstr = &str_yes;
  815.     newsp = -2;
  816.     if (cmd->ucmd.ccmd.cc_true) {
  817. #ifdef DEBUGGING
  818.         if (debug) {
  819.         debname[dlevel] = 't';
  820.         debdelim[dlevel] = '_';
  821.         if (++dlevel >= dlmax)
  822.             grow_dlevel();
  823.         }
  824. #endif
  825.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  826.         st = stack->ary_array;    /* possibly reallocated */
  827.         retstr = st[newsp];
  828.     }
  829.     curspat = oldspat;
  830.     if (savestack->ary_fill > oldsave)
  831.         restorelist(oldsave);
  832. #ifdef DEBUGGING
  833.     dlevel = olddlevel;
  834. #endif
  835.     cmd = cmd->ucmd.ccmd.cc_alt;
  836.     goto tail_recursion_entry;
  837.     case C_ELSE:
  838.     oldspat = curspat;
  839.     oldsave = savestack->ary_fill;
  840. #ifdef DEBUGGING
  841.     olddlevel = dlevel;
  842. #endif
  843.     retstr = &str_undef;
  844.     newsp = -2;
  845.     if (cmd->ucmd.ccmd.cc_true) {
  846. #ifdef DEBUGGING
  847.         if (debug) {
  848.         debname[dlevel] = 'e';
  849.         debdelim[dlevel] = '_';
  850.         if (++dlevel >= dlmax)
  851.             grow_dlevel();
  852.         }
  853. #endif
  854.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  855.         st = stack->ary_array;    /* possibly reallocated */
  856.         retstr = st[newsp];
  857.     }
  858.     curspat = oldspat;
  859.     if (savestack->ary_fill > oldsave)
  860.         restorelist(oldsave);
  861. #ifdef DEBUGGING
  862.     dlevel = olddlevel;
  863. #endif
  864.     break;
  865.     case C_BLOCK:
  866.     case C_WHILE:
  867.     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  868.         cmdflags |= CF_ONCE;
  869.         if (++loop_ptr >= loop_max) {
  870.         loop_max += 128;
  871.         Renew(loop_stack, loop_max, struct loop);
  872.         }
  873.         loop_stack[loop_ptr].loop_label = cmd->c_label;
  874.         loop_stack[loop_ptr].loop_sp = sp;
  875. #ifdef DEBUGGING
  876.         if (debug & 4) {
  877.         deb("(Pushing label #%d %s)\n",
  878.           loop_ptr, cmd->c_label ? cmd->c_label : "");
  879.         }
  880. #endif
  881.     }
  882. #ifdef JMPCLOBBER
  883.     cmdparm = cmd;
  884. #endif
  885.     match = setjmp(loop_stack[loop_ptr].loop_env);
  886.     if (match) {
  887.         st = stack->ary_array;    /* possibly reallocated */
  888. #ifdef JMPCLOBBER
  889.         cmd = cmdparm;
  890.         cmdflags = cmd->c_flags|CF_ONCE;
  891.         go_to = goto_targ;
  892. #endif
  893.         if (savestack->ary_fill > oldsave)
  894.         restorelist(oldsave);
  895.         switch (match) {
  896.         default:
  897.         fatal("longjmp returned bad value (%d)",match);
  898.         case O_LAST:
  899.         if (lastretstr) {
  900.             retstr = lastretstr;
  901.             newsp = -2;
  902.         }
  903.         else {
  904.             newsp = sp + lastsize;
  905.             retstr = st[newsp];
  906.         }
  907.         curspat = oldspat;
  908.         goto next_cmd;
  909.         case O_NEXT:
  910. #ifdef JMPCLOBBER
  911.         newsp = -2;
  912.         retstr = &str_undef;
  913. #endif
  914.         goto next_iter;
  915.         case O_REDO:
  916. #ifdef DEBUGGING
  917.         dlevel = olddlevel;
  918. #endif
  919. #ifdef JMPCLOBBER
  920.         newsp = -2;
  921.         retstr = &str_undef;
  922. #endif
  923.         goto doit;
  924.         }
  925.     }
  926.     oldspat = curspat;
  927.     oldsave = savestack->ary_fill;
  928. #ifdef DEBUGGING
  929.     olddlevel = dlevel;
  930. #endif
  931.     doit:
  932.     if (cmd->ucmd.ccmd.cc_true) {
  933. #ifdef DEBUGGING
  934.         if (debug) {
  935.         debname[dlevel] = 't';
  936.         debdelim[dlevel] = '_';
  937.         if (++dlevel >= dlmax)
  938.             grow_dlevel();
  939.         }
  940. #endif
  941.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  942.         st = stack->ary_array;    /* possibly reallocated */
  943.         retstr = st[newsp];
  944.     }
  945.     /* actually, this spot is rarely reached anymore since the above
  946.      * cmd_exec() returns through longjmp().  Hooray for structure.
  947.      */
  948.       next_iter:
  949. #ifdef DEBUGGING
  950.     dlevel = olddlevel;
  951. #endif
  952.     if (cmd->ucmd.ccmd.cc_alt) {
  953. #ifdef DEBUGGING
  954.         if (debug) {
  955.         debname[dlevel] = 'a';
  956.         debdelim[dlevel] = '_';
  957.         if (++dlevel >= dlmax)
  958.             grow_dlevel();
  959.         }
  960. #endif
  961.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  962.         st = stack->ary_array;    /* possibly reallocated */
  963.         retstr = st[newsp];
  964.     }
  965.       finish_while:
  966.     curspat = oldspat;
  967.     if (savestack->ary_fill > oldsave) {
  968.         if (cmdflags & CF_TERM) {
  969.         for (match = sp + 1; match <= newsp; match++)
  970.             st[match] = str_mortal(st[match]);
  971.         retstr = st[newsp];
  972.         }
  973.         restorelist(oldsave);
  974.     }
  975. #ifdef DEBUGGING
  976.     dlevel = olddlevel - 1;
  977. #endif
  978.     if (cmd->c_type != C_BLOCK)
  979.         goto until_loop;    /* go back and evaluate conditional again */
  980.     }
  981.     if (cmdflags & CF_LOOP) {
  982.     cmdflags |= CF_COND;        /* now test the condition */
  983. #ifdef DEBUGGING
  984.     dlevel = entdlevel;
  985. #endif
  986.     goto until_loop;
  987.     }
  988.   next_cmd:
  989.  
  990. #ifdef macintosh
  991.     SpinMacCursor();
  992. #endif
  993.  
  994.     if (cmdflags & CF_ONCE) {
  995. #ifdef DEBUGGING
  996.     if (debug & 4) {
  997.         tmps = loop_stack[loop_ptr].loop_label;
  998.         deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  999.     }
  1000. #endif
  1001.     loop_ptr--;
  1002.     if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
  1003.       savestack->ary_fill > aryoptsave)
  1004.         restorelist(aryoptsave);
  1005.     }
  1006.     cmd = cmd->c_next;
  1007.     goto tail_recursion_entry;
  1008. }
  1009.  
  1010. #ifdef DEBUGGING
  1011. #  ifndef I_VARARGS
  1012. /*VARARGS1*/
  1013. void deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  1014. char *pat;
  1015. {
  1016.     register int i;
  1017.  
  1018. #ifdef macintosh
  1019.     fprintf(perldbg,"%-4ld",(long)curcmd->c_line);
  1020.     for (i=0; i<dlevel; i++)
  1021.     fprintf(perldbg,"%c%c ",debname[i],debdelim[i]);
  1022.     fprintf(perldbg,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1023. #else
  1024.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1025.     for (i=0; i<dlevel; i++)
  1026.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1027.     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1028. #endif
  1029. }
  1030. #  else
  1031. /*VARARGS1*/
  1032. void deb(va_alist)
  1033. va_dcl
  1034. {
  1035.     va_list args;
  1036.     char *pat;
  1037.     register int i;
  1038.  
  1039.     va_start(args);
  1040.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1041.     for (i=0; i<dlevel; i++)
  1042.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1043.  
  1044.     pat = va_arg(args, char *);
  1045.     (void) vfprintf(stderr,pat,args);
  1046.     va_end( args );
  1047. }
  1048. #  endif
  1049. #endif
  1050.  
  1051. int
  1052. copyopt(cmd,which)
  1053. register CMD *cmd;
  1054. register CMD *which;
  1055. {
  1056.     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  1057.     cmd->c_flags |= which->c_flags;
  1058.     cmd->c_short = which->c_short;
  1059.     cmd->c_slen = which->c_slen;
  1060.     cmd->c_stab = which->c_stab;
  1061.     return cmd->c_flags;
  1062. }
  1063.  
  1064. ARRAY *
  1065. saveary(stab)
  1066. STAB *stab;
  1067. {
  1068.     register STR *str;
  1069.  
  1070.     str = Str_new(10,0);
  1071.     str->str_state = SS_SARY;
  1072.     str->str_u.str_stab = stab;
  1073.     if (str->str_ptr) {
  1074.     Safefree(str->str_ptr);
  1075.     str->str_ptr = Nullch;
  1076.     str->str_len = 0;
  1077.     }
  1078.     str->str_ptr = (char*)stab_array(stab);
  1079.     (void)apush(savestack,str); /* save array ptr */
  1080.     stab_xarray(stab) = Null(ARRAY*);
  1081.     return stab_xarray(aadd(stab));
  1082. }
  1083.  
  1084. HASH *
  1085. savehash(stab)
  1086. STAB *stab;
  1087. {
  1088.     register STR *str;
  1089.  
  1090.     str = Str_new(11,0);
  1091.     str->str_state = SS_SHASH;
  1092.     str->str_u.str_stab = stab;
  1093.     if (str->str_ptr) {
  1094.     Safefree(str->str_ptr);
  1095.     str->str_ptr = Nullch;
  1096.     str->str_len = 0;
  1097.     }
  1098.     str->str_ptr = (char*)stab_hash(stab);
  1099.     (void)apush(savestack,str); /* save hash ptr */
  1100.     stab_xhash(stab) = Null(HASH*);
  1101.     return stab_xhash(hadd(stab));
  1102. }
  1103.  
  1104. void
  1105. saveitem(item)
  1106. register STR *item;
  1107. {
  1108.     register STR *str;
  1109.  
  1110.     (void)apush(savestack,item);        /* remember the pointer */
  1111.     str = Str_new(12,0);
  1112.     str_sset(str,item);
  1113.     (void)apush(savestack,str);            /* remember the value */
  1114. }
  1115.  
  1116. void
  1117. saveint(intp)
  1118. int *intp;
  1119. {
  1120.     register STR *str;
  1121.  
  1122.     str = Str_new(13,0);
  1123.     str->str_state = SS_SINT;
  1124.     str->str_u.str_useful = (long)*intp;    /* remember value */
  1125.     if (str->str_ptr) {
  1126.     Safefree(str->str_ptr);
  1127.     str->str_len = 0;
  1128.     }
  1129.     str->str_ptr = (char*)intp;        /* remember pointer */
  1130.     (void)apush(savestack,str);
  1131. }
  1132.  
  1133. void
  1134. savelong(longp)
  1135. long *longp;
  1136. {
  1137.     register STR *str;
  1138.  
  1139.     str = Str_new(14,0);
  1140.     str->str_state = SS_SLONG;
  1141.     str->str_u.str_useful = *longp;        /* remember value */
  1142.     if (str->str_ptr) {
  1143.     Safefree(str->str_ptr);
  1144.     str->str_len = 0;
  1145.     }
  1146.     str->str_ptr = (char*)longp;        /* remember pointer */
  1147.     (void)apush(savestack,str);
  1148. }
  1149.  
  1150. void
  1151. savesptr(sptr)
  1152. STR **sptr;
  1153. {
  1154.     register STR *str;
  1155.  
  1156.     str = Str_new(15,0);
  1157.     str->str_state = SS_SSTRP;
  1158.     str->str_magic = *sptr;        /* remember value */
  1159.     if (str->str_ptr) {
  1160.     Safefree(str->str_ptr);
  1161.     str->str_len = 0;
  1162.     }
  1163.     str->str_ptr = (char*)sptr;        /* remember pointer */
  1164.     (void)apush(savestack,str);
  1165. }
  1166.  
  1167. void
  1168. savenostab(stab)
  1169. STAB *stab;
  1170. {
  1171.     register STR *str;
  1172.  
  1173.     str = Str_new(16,0);
  1174.     str->str_state = SS_SNSTAB;
  1175.     str->str_magic = (STR*)stab;    /* remember which stab to free */
  1176.     (void)apush(savestack,str);
  1177. }
  1178.  
  1179. void
  1180. savehptr(hptr)
  1181. HASH **hptr;
  1182. {
  1183.     register STR *str;
  1184.  
  1185.     str = Str_new(17,0);
  1186.     str->str_state = SS_SHPTR;
  1187.     str->str_u.str_hash = *hptr;    /* remember value */
  1188.     if (str->str_ptr) {
  1189.     Safefree(str->str_ptr);
  1190.     str->str_len = 0;
  1191.     }
  1192.     str->str_ptr = (char*)hptr;        /* remember pointer */
  1193.     (void)apush(savestack,str);
  1194. }
  1195.  
  1196. void
  1197. saveaptr(aptr)
  1198. ARRAY **aptr;
  1199. {
  1200.     register STR *str;
  1201.  
  1202.     str = Str_new(17,0);
  1203.     str->str_state = SS_SAPTR;
  1204.     str->str_u.str_array = *aptr;    /* remember value */
  1205.     if (str->str_ptr) {
  1206.     Safefree(str->str_ptr);
  1207.     str->str_len = 0;
  1208.     }
  1209.     str->str_ptr = (char*)aptr;        /* remember pointer */
  1210.     (void)apush(savestack,str);
  1211. }
  1212.  
  1213. void
  1214. savelist(sarg,maxsarg)
  1215. register STR **sarg;
  1216. int maxsarg;
  1217. {
  1218.     register STR *str;
  1219.     register int i;
  1220.  
  1221.     for (i = 1; i <= maxsarg; i++) {
  1222.     (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1223.     str = Str_new(18,0);
  1224.     str_sset(str,sarg[i]);
  1225.     (void)apush(savestack,str);            /* remember the value */
  1226.     sarg[i]->str_u.str_useful = -1;
  1227.     }
  1228. }
  1229.  
  1230. void
  1231. restorelist(base)
  1232. int base;
  1233. {
  1234.     register STR *str;
  1235.     register STR *value;
  1236.     register STAB *stab;
  1237.  
  1238.     if (base < -1)
  1239.     fatal("panic: corrupt saved stack index");
  1240.     while (savestack->ary_fill > base) {
  1241.     value = apop(savestack);
  1242.     switch (value->str_state) {
  1243.     case SS_NORM:                /* normal string */
  1244.     case SS_INCR:
  1245.         str = apop(savestack);
  1246.         str_replace(str,value);
  1247.         STABSET(str);
  1248.         break;
  1249.     case SS_SARY:                /* array reference */
  1250.         stab = value->str_u.str_stab;
  1251.         afree(stab_xarray(stab));
  1252.         stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1253.         value->str_ptr = Nullch;
  1254.         str_free(value);
  1255.         break;
  1256.     case SS_SHASH:                /* hash reference */
  1257.         stab = value->str_u.str_stab;
  1258. #ifndef macintosh
  1259.         (void)hfree(stab_xhash(stab), FALSE);
  1260. #else
  1261.         hfree(stab_xhash(stab), FALSE);
  1262. #endif
  1263.         stab_xhash(stab) = (HASH*)value->str_ptr;
  1264.         value->str_ptr = Nullch;
  1265.         str_free(value);
  1266.         break;
  1267.     case SS_SINT:                /* int reference */
  1268.         *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1269.         value->str_ptr = Nullch;
  1270.         str_free(value);
  1271.         break;
  1272.     case SS_SLONG:                /* long reference */
  1273.         *((long*)value->str_ptr) = value->str_u.str_useful;
  1274.         value->str_ptr = Nullch;
  1275.         str_free(value);
  1276.         break;
  1277.     case SS_SSTRP:                /* STR* reference */
  1278.         *((STR**)value->str_ptr) = value->str_magic;
  1279.         value->str_magic = Nullstr;
  1280.         value->str_ptr = Nullch;
  1281.         str_free(value);
  1282.         break;
  1283.     case SS_SHPTR:                /* HASH* reference */
  1284.         *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1285.         value->str_ptr = Nullch;
  1286.         str_free(value);
  1287.         break;
  1288.     case SS_SAPTR:                /* ARRAY* reference */
  1289.         *((ARRAY**)value->str_ptr) = value->str_u.str_array;
  1290.         value->str_ptr = Nullch;
  1291.         str_free(value);
  1292.         break;
  1293.     case SS_SNSTAB:
  1294.         stab = (STAB*)value->str_magic;
  1295.         value->str_magic = Nullstr;
  1296. #ifndef macintosh
  1297.         (void)stab_clear(stab);
  1298. #else
  1299.         stab_clear(stab);
  1300. #endif
  1301.         str_free(value);
  1302.         break;
  1303.     case SS_SCSV:                /* callsave structure */
  1304.         {
  1305.         CSV *csv = (CSV*) value->str_ptr;
  1306.  
  1307.         curcmd = csv->curcmd;
  1308.         curcsv = csv->curcsv;
  1309.         csv->sub->depth = csv->depth;
  1310.         if (csv->hasargs) {        /* put back old @_ */
  1311.             afree(csv->argarray);
  1312.             stab_xarray(defstab) = csv->savearray;
  1313.         }
  1314.         str_free(value);
  1315.         }
  1316.         break;
  1317.     default:
  1318.         fatal("panic: restorelist inconsistency");
  1319.     }
  1320.     }
  1321. }
  1322.  
  1323. #ifdef DEBUGGING
  1324. void
  1325. grow_dlevel()
  1326. {
  1327.     dlmax += 128;
  1328.     Renew(debname, dlmax, char);
  1329.     Renew(debdelim, dlmax, char);
  1330. }
  1331. #endif
  1332.  
  1333. #ifdef macintosh
  1334. void reinit_cmd()
  1335. {
  1336.     memset(&strchop, 0, sizeof(STR));
  1337. }
  1338. #endif
  1339.